package com.btcode.netty.server.handler.hrt;

import com.btcode.common.ByteUnit;
import com.btcode.netty.server.handler.AbstractHrtDecoder;
import com.btcode.netty.server.session.IoSession;
import com.btcode.netty.server.session.SessionManager;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.util.ReferenceCountUtil;

import java.util.List;

public class LightingDecoder extends AbstractHrtDecoder {

    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
        try {
            //从站编号加上数据长度，必须有3位
            if (in.readableBytes() < 3) {
                log.info("数据长度不够");
                return;
            }
            in.markReaderIndex();
            int readIndex = in.readerIndex();
            byte[] mnByte = new byte[1];
            in.getBytes(readIndex, mnByte);

            byte[] dataLengthByte = new byte[1];
            in.getBytes(readIndex + 2, dataLengthByte);

            if (dataLengthByte[0] == 0) {
                // 如果长度为0 说明是心跳包
                ByteBuf channelBuffer = in.readBytes(3);
                int mn = ByteUnit.ConvertByteToInt8(mnByte[0]);
                out.add(channelBuffer);
            }

            if ((dataLengthByte[0] & 0xff) < 0) {
                String msg = getByteBufHexStr(in);
                log.error("长度为负数:" + msg);
                in.clear();
                ctx.close();
                return;
            }
            int expectDataLength = 1 + 1 + 1 + (dataLengthByte[0] & 0xff) + 2;//1位从站编号，1位功能码，1位数据长度，n位数据，2位校验位
            if (in.readableBytes() < expectDataLength) {
                //获取的数据长度和期望的长度不匹配，说明数据还没有接受完整，返回null等待数据
                log.info("数据长度不够，期望：" + expectDataLength + "，实际：" + in.readableBytes());
                in.resetReaderIndex();
            }
            else {
                ByteBuf channelBuffer = in.readBytes(expectDataLength);
                out.add(channelBuffer);
            }
        }
        catch (Exception e) {
            log.error("报文粘拆包处理出错:" + getByteBufHexStr(in), e);
        }
    }

    @Override
    public String getMnFromChannel(ChannelHandlerContext ctx, ByteBuf msgDecodeOut) {
        byte[] bytes = getByteBufBytes(msgDecodeOut);
        if (bytes.length == 3) {
            return String.valueOf(ByteUnit.ConvertByteToInt8(bytes[0]));
        }
        else {
            IoSession session = SessionManager.INSTANCE.getSessionByChannel(ctx.channel());
            if (session == null) {//雷电限制于下端设备直接透传方式，只有心跳带有站点编号
                log.error("下端没有首先传输带ID的心跳报文" + session);
                ReferenceCountUtil.release(msgDecodeOut);
                ctx.close();
                return null;
            }
            return session.getUserId();
        }
    }

    @Override
    public boolean[] shouldCheckConflictAndUseNewConn() {
        return new boolean[]{true, false};
    }
}
